/*****************************************************************************
 * file  : systask.c
 * creat : apleilx
 * note :  除初始化外，禁止该任务及其子程序使用含有阻塞的功能，包括数据存储，USB操作等等
 * data  : 2019/07/02
 *******************************************************************************/
#include "framework.h"

#include "bsp_api.h"
#include "nor_cmd.h"

#include "lut/nand_lut.h"

#include "swap.h"

#include "fat_file_opt.h"
#include "simp_fat_update.h"

/*****************************************************************************
 * @brief   const define
 *****************************************************************************/
extern nand_lut_type nand_dev;

/*****************************************************************************
 * @brief   function
 *****************************************************************************/
uint8_t nand_get_blk_dat(nand_lut_type *lut, uint32_t addr_offset, uint8_t *pdat, uint16_t len);

/*****************************************************************************
 * @brief   simp_fat_tab_erase.
 * @param   none
 * @return  none
 *****************************************************************************/
void simp_fat_tab_erase(void)
{
	switch (efat.fsel)
	{
	case 0:
		nor_sector_erase(SWNOR_BASE_SIMP_FAT_TAB);
		nor_sector_erase(SWNOR_BASE_SIMP_FAT_TAB + 0x1000);
		nor_sector_erase(SWNOR_BASE_SIMP_FAT_TAB + 0x2000);
		nor_sector_erase(SWNOR_BASE_SIMP_FAT_TAB + 0x3000);
		break;

	default:
		break;
	}
}

/*****************************************************************************
 * @brief   simp_fat_tab_write.
 * @param   none
 * @return  none
 *****************************************************************************/
void simp_fat_tab_write(uint32_t addr_offset, uint8_t *buff, uint32_t len)
{
	switch (efat.fsel)
	{
	case 0:
		nor_write_multi(SWNOR_BASE_SIMP_FAT_TAB + addr_offset, len, buff);
		break;

	default:
		break;
	}
}

/*****************************************************************************
 * @brief   simp_fat_tab_save.
 * @param   none
 * @return  none
 *****************************************************************************/
void simp_fat_tab_save(void)
{
	switch (efat.fsel)
	{
	case 0:
		break;

	default:
		break;
	}
}

/*****************************************************************************
 * @brief   simp_fat_main_write_start.
 * @param   none
 * @return  none
 *****************************************************************************/
void simp_fat_main_write_start(void)
{
	uint8_t falsh_st;

	switch (efat.fsel)
	{
	case 0:
	{
		// flash write enable
	}
	break;

	default:
		break;
	}
}

/*****************************************************************************
 * @brief   simp_fat_main_write_start.
 * @param   none
 * @return  none
 *****************************************************************************/
void simp_fat_main_write_end(void)
{
	switch (efat.fsel)
	{
	case 0:
		// flash write disable
		break;

	default:
		break;
	}
}

/*****************************************************************************
 * @brief   simp_fat_main_write_start.
 * @param   none
 * @return  none
 *****************************************************************************/
void simp_fat_main_write(uint32_t block)
{
	switch (efat.fsel)
	{
	case 0:
		nand_dev.api.block_write(block + NAND_BASE_SIMP_FAT, nand_get_blk_dat);
		break;

	default:
		break;
	}
}

/*****************************************************************************
 * @brief   nand_get_blk_dat
 * @param   addr pdat len
 * @return  non
 *****************************************************************************/
uint8_t nand_get_blk_dat(nand_lut_type *lut, uint32_t addr_offset, uint8_t *pdat, uint16_t len)
{
	UU32 len_back;
	int fil_site = efat.wr_fil_block * efat.wr_block_size + addr_offset;

	// 读取文件
	if (fil_site < efat.main_len)
	{
		// 文件定位-仅在回写时重新定位
		if (fil_site < efat.wr_site_old)
		{
			fat_fil_seek(efat.fil, fil_site + efat.main_site);
			dbg_print("nand block write reseek @ %04X, offset : %d", efat.wr_fil_block, addr_offset);
		}

		// aes mode
		if (efat.main_aes_mode == 0x55)
		{
			int site, len_rd;

			if (len + fil_site < efat.main_len)
			{
				len_rd = len;
			}
			else
			{
				len_rd = efat.main_len - fil_site;
			}

			efat.fst = fat_fil_read(efat.fil, efat.buff, len, &len_back);

			// decode
			for (site = 0; site < len_back && (fil_site + site < efat.main_len); site += 16)
			{
				mbedtls_aes_crypt_ecb(efat.aes_obj, MBEDTLS_AES_DECRYPT, &efat.buff[site], &(pdat[site]));
				if (efat.sha_en)
					mbedtls_sha256_update(efat.sha_obj, &pdat[site], 16);
				if (efat.md5_en)
					mbedtls_md5_update(efat.md5_obj, &pdat[site], 16);
			}
		}
		// nor mode
		else
		{
			int lenhash;

			// read data
			efat.fst = fat_fil_read(efat.fil, pdat, len, &len_back);

			lenhash = len_back;
			if (fil_site + len_back > efat.main_len)
				lenhash = efat.main_len - fil_site;

			if (efat.sha_en)
				mbedtls_sha256_update(efat.sha_obj, pdat, lenhash);
			if (efat.md5_en)
				mbedtls_md5_update(efat.md5_obj, pdat, lenhash);
		}

		if (len_back < len)
		{
			set_u8(&pdat[len_back], 0xFF, len - len_back);
		}

		efat.wr_site_old = fil_site;
	}
	else
	{
		set_u8(pdat, 0xFF, len);
	}

	return 0;
}
